import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Vector;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * @author dbru
 * @version 0.89
 */
public class StrucutreParser extends DefaultHandler {
	private String PROJECT = "PROJECT";
	private String FILE = "FILE";
	private String DIR = "DIR";
	private String HEADER = "HEADER";
	private String FOOTER = "FOOTER";
	private String BODY = "BODY";
	private String DATABASE = "DATABASE";
	private String OPENCON = "OPENCON";
	private String CLOSECON = "CLOSECON";
	private String FUNCINC = "FUNCINC";
	private String INC = "INC";

	private String ATTRNAME = "name";
	private String ATTRTYPE = "type";
	private String ATTRPATH = "path";
	private String ATTRMETHNAME = "methName";
	private String ATTRPHPTYPE = "phpType";
	private String ATTRSAVECON = "saveCon";
	private String ATTRSDB = "db";

	private boolean project = false;
	private boolean database = false;
	private boolean funcinc = false;
	private File xmlFile = null;
	private File currentDir = null;
	private File baseDir = null;
	private PHPDocInfo doc = null;

	public StrucutreParser() {

		xmlFile = new File("./Input.xml");
		baseDir = new File("./");
		loadXMLDocument();
	}

	private void loadXMLDocument() {

		try {
			SAXParserFactory spf = SAXParserFactory.newInstance();
			// spf.setValidating(true);

			SAXParser sp = spf.newSAXParser();
			sp.parse(xmlFile, this);

		} catch (ParserConfigurationException e) {
			throw new RuntimeException(e);
		} catch (SAXException e) {
			throw new RuntimeException(e);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void startElement(String namespaceURI, String localName,
			String rawName, Attributes attrs) {

		if (!project) {
			if (rawName.equals(PROJECT)) {
				String name = attrs.getValue(ATTRNAME);

				baseDir = new File(name);

				currentDir = baseDir;
				project = baseDir.mkdir();
				doc = new PHPDocInfo();
			}
		} else {
			if (rawName.equals(DIR)) {
				String name = attrs.getValue(ATTRNAME);

				currentDir = new File(currentDir.getAbsolutePath() + "/" + name);
				currentDir.mkdir();

			} else if (rawName.equals(FILE)) {

				String name = attrs.getValue(ATTRNAME);

				String type = null;
				try {
					type = attrs.getValue(ATTRTYPE);
				} catch (Exception e) {
					type = "unknown";
				}

				String phpType = null;

				try {
					phpType = attrs.getValue(ATTRPHPTYPE);
				} catch (Exception e) {
					phpType = "unknown";
				}

				boolean db = false;
				try {
					db = attrs.getValue(ATTRSDB).equals("true") ? true : false;
				} catch (Exception e) {
					db = false;
				}

				File file = new File(currentDir.getAbsolutePath() + "/" + name
						+ "." + type);

				if (!file.exists()) {
					try {
						file.createNewFile();
					} catch (IOException e) {
						e.printStackTrace();
					}

					writeFileContent(file, type, phpType, db);
				}

			} else if (rawName.equals(HEADER)) {
				doc.setHeaderFile(attrs.getValue(ATTRPATH));
				doc.setHeaderMethod(attrs.getValue(ATTRMETHNAME));
			} else if (rawName.equals(FOOTER)) {
				doc.setFooterFile(attrs.getValue(ATTRPATH));
				doc.setFooterMethod(attrs.getValue(ATTRMETHNAME));
			} else if (rawName.equals(BODY)) {
				doc.setBodyFile(attrs.getValue(ATTRPATH));
			} else if (rawName.equals(DATABASE)) {
				database = true;
				doc.setDatabaseFile(attrs.getValue(ATTRPATH));
				doc.setDatabaseSaveCon(attrs.getValue(ATTRSAVECON).equals(
						"true") ? true : false);
			} else if (rawName.equals(OPENCON)) {
				if (database) {
					doc.setDbOpenConMethod(attrs.getValue(ATTRMETHNAME));
				}
			} else if (rawName.equals(CLOSECON)) {
				if (database) {
					doc.setDbCloseConMethod(attrs.getValue(ATTRMETHNAME));
				}
			} else if (rawName.equals(FUNCINC)) {
				funcinc = true;
			} else if (rawName.equals(INC)) {
				doc.addInclude(attrs.getValue(ATTRPATH));
			}
		}
	}

	private void writeFileContent(File file, String type, String phpType,
			boolean db) {
		if (type.equals("php")) {

			try {
				BufferedWriter bw = new BufferedWriter(new FileWriter(file));
				bw.write(doc.createNewPHPFile(file.getName(), phpType, db));
				bw.newLine();
				bw.flush();
				bw.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void endElement(String namespaceURI, String localName, String rawName) {
		if (project) {
			if (rawName.equals(PROJECT)) {
				project = false;
			} else if (rawName.equals(DIR)) {
				currentDir = currentDir.getParentFile();
			} else if (rawName.equals(DATABASE)) {
				database = false;
			} else if (rawName.equals(FUNCINC)) {
				funcinc = false;
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void error(SAXParseException someException) throws SAXException {
		System.err.println("Error on line " + someException.getLineNumber()
				+ " " + someException.getMessage());

	}

	/**
	 * {@inheritDoc}
	 */
	public void fatalError(SAXParseException someException) throws SAXException {
		System.err.println("Fatal Error on line "
				+ someException.getLineNumber() + " "
				+ someException.getMessage());

	}

	/**
	 * {@inheritDoc}
	 */
	public void warning(SAXParseException someException) throws SAXException {
		System.err.println("Warning on line " + someException.getLineNumber()
				+ " " + someException.getMessage());

	}

	public static void main(String[] args) {
		new StrucutreParser();
	}

	private class PHPDocInfo {
		private String headerFile = null;
		private String headerMethod = null;
		private String footerFile = null;
		private String footerMethod = null;
		private String bodyFile = null;
		private String bodyFileContent = null;
		private String databaseFile = null;
		private boolean databaseSaveCon = false;
		private String dbOpenConMethod = null;
		private String dbCloseConMethod = null;
		private Vector includesVec = null;

		private String phpFileComment = null;

		public PHPDocInfo() {
			includesVec = new Vector();
		}

		public String createNewPHPFile(String name, String phpType, boolean db) {
			String phpFile = "";

			phpFile += "<?php\n";
			phpFile += "// +----------------------------------------------------------------------------------------------+\n";
			phpFile += "// | Projekt       Lepa                                                                           |\n";
			phpFile += "// | Dateiname     " + name +"                                                                    |\n";
			phpFile += "// | Plattform     PHP 5.1 / Apache 2.0                                                           |\n";
			phpFile += "// |                                                                                              |\n";
			phpFile += "// | Autor         Daniel Brun     (dbru)                                                         |\n";
			phpFile += "// | Datum         12.03.2009                                                                     |\n";
			phpFile += "// |                                                                                              |\n";
			phpFile += "// | Beschreibung  Was tut das Ding?                                                              |\n";
			phpFile += "// |                                                                                              |\n";
			phpFile += "// | Version  Datum       Beschreibung                                                  Autor     |\n";
			phpFile += "// | -------  ----------  ------------                                                  -----     |\n";
			phpFile += "// | V1.00    2009-03-12  erstellt                                                      dbru      |\n";
			phpFile += "// |                                                                                              |\n";
			phpFile += "// +----------------------------------------------------------------------------------------------+\n";
			if (phpType.equals("page")) {
				phpFile += "\tinclude '" + headerFile + "';\n";

				if (!headerFile.equals(footerFile)) {
					phpFile += "\tinclude '" + footerFile + "';\n";
				}

				if (db) {
					phpFile += "\tinclude '" + databaseFile + "';\n";
				}

				for (int i = 0; i < includesVec.size(); i++) {
					phpFile += "\tinclude '" + (String) includesVec.get(i)
							+ "';\n";
				}

				phpFile += "\n\t" + headerMethod + "();\n";

				if (db) {
					if (databaseSaveCon) {
						phpFile += "\t$DBConnection = " + dbOpenConMethod
								+ "();\n";
					} else {
						phpFile += "\t" + dbOpenConMethod + "();\n";
					}
				}

				phpFile += bodyFileContent;

				if (db) {
					if (databaseSaveCon) {
						phpFile += "\t" + dbCloseConMethod
								+ "($DBConnection);\n";
					} else {
						phpFile += "\t" + dbCloseConMethod + "();\n";
					}
				}

				phpFile += "\t" + footerMethod + "();\n";
			} else if (phpType.equals("function")) {
				// empty
			} else {

			}

			phpFile += "?>";
			return phpFile;
		}

		public String getPhpFileComment() {
			return phpFileComment;
		}

		public void setPhpFileComment(String somePhpFileComment) {
			phpFileComment = somePhpFileComment;
		}

		public String getHeaderFile() {
			return headerFile;
		}

		public void setHeaderFile(String someHeaderFile) {
			headerFile = someHeaderFile;
		}

		public String getHeaderMethod() {
			return headerMethod;
		}

		public void setHeaderMethod(String someHeaderMethod) {
			headerMethod = someHeaderMethod;
		}

		public String getFooterFile() {
			return footerFile;
		}

		public void setFooterFile(String someFooterFile) {
			footerFile = someFooterFile;
		}

		public String getFooterMethod() {
			return footerMethod;
		}

		public void setFooterMethod(String someFooterMethod) {
			footerMethod = someFooterMethod;
		}

		public String getBodyFile() {
			return bodyFile;
		}

		public void setBodyFile(String someBodyFile) {
			bodyFile = someBodyFile;

			try {
				BufferedReader br = new BufferedReader(new FileReader(new File(
						bodyFile)));
				String line = null;
				bodyFileContent = "\n";
				while ((line = br.readLine()) != null) {
					bodyFileContent += line + "\n";
				}
				br.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		public String getDatabaseFile() {
			return databaseFile;
		}

		public void setDatabaseFile(String someDatabaseFile) {
			databaseFile = someDatabaseFile;
		}

		public String getDbOpenConMethod() {
			return dbOpenConMethod;
		}

		public void setDbOpenConMethod(String someDbOpenConMethod) {
			dbOpenConMethod = someDbOpenConMethod;
		}

		public String getDbCloseConMethod() {
			return dbCloseConMethod;
		}

		public void setDbCloseConMethod(String someDbCloseConMethod) {
			dbCloseConMethod = someDbCloseConMethod;
		}

		public Vector getIncludesVec() {
			return includesVec;
		}

		public void setIncludesVec(Vector someIncludesVec) {
			includesVec = someIncludesVec;
		}

		public void addInclude(String somePath) {
			includesVec.add(somePath);
		}

		public boolean isDatabaseSaveCon() {
			return databaseSaveCon;
		}

		public void setDatabaseSaveCon(boolean someDatabaseSaveCon) {
			databaseSaveCon = someDatabaseSaveCon;
		}

	}
}
